package com.showgood.model {
	import com.showgood.core.AbstractProxy;
	import com.showgood.config.Config;
	import com.showgood.config.SangoConst;
	import com.showgood.socket.AbstractSocketCommand;
	import com.showgood.socket.ArraySocketCommand;
	import com.showgood.socket.SingleSocketCommand;
	import com.showgood.socket.SocketCommandFactory;
	import com.showgood.socket.SocketConsts;
	import com.showgood.vo.BaseVO;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.Socket;
	import flash.utils.ByteArray;
	import flash.utils.getQualifiedClassName;
	import org.as3commons.lang.StringBuffer;

	/**
	 * 网络服务
	 * @author bianpeng
	 */
	public class SocketProxy extends AbstractProxy {
		private static const PREHEAD_LENGTH:int = 2;
		private var _socket:Socket = new Socket();
		// 下一个VO是否准备好了
		private var _step:int = 0;		// 标记走到哪一步了, 类似于NIO...
		// 数据长度等信息
		private var _len:int = 0;		//
		
		public function SocketProxy() {
			connectSocketServer();
		}
		private function onSecurityError(event:SecurityErrorEvent):void {
			_logger.error('socket security error');
		}
		private function onConnect(event:Event):void {
			_logger.info('socket connected');
			// 连接完毕, 显示游戏login窗口
			// socket connected , get username/password 
			sendNotification(SangoConst.SOCKET_READY_TO_LOGIN);
		}
		private function onClose(event:Event):void {
			_logger.info('socket closed');
		}
		private function onIoError(event:IOErrorEvent):void {
			_logger.error('socket io error');
		}
		private function onSocketData(event:ProgressEvent):void {
			parseCommand();
		}
		/**
		 * 连接游戏服务器
		 */
		private function connectSocketServer():void {
			_socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
			_socket.addEventListener(Event.CONNECT, onConnect);
			_socket.addEventListener(Event.CLOSE, onClose);
			_socket.addEventListener(IOErrorEvent.IO_ERROR, onIoError);
			_socket.addEventListener(ProgressEvent.SOCKET_DATA, onSocketData);
			
			_socket.connect(Config.SOCKET_SERVER, Config.SOCKET_PORT);
		}
		override public function onRemove():void {
			_socket.close();
		}
		/**
		 * 最后用来发送命令用的
		 * @param	cmd
		 */
		private function sendCommand(cmd:AbstractSocketCommand):void {
			var byteArray:ByteArray = new ByteArray();
			SocketCommandFactory.instance.pack(cmd, byteArray);
			_socket.writeBytes(byteArray);
			_socket.flush();
		}
		/**
		 * 发送单个VO
		 * @param	msg
		 * @param	stamp
		 * @param	data
		 */
		public function sendSingleVo(msg:int, stamp:int, data:BaseVO):void {
			var _command:AbstractSocketCommand = new SingleSocketCommand(msg, stamp, data);
			sendCommand(_command);
		}
		/**
		 * 发送一组VO
		 * @param	msg
		 * @param	stamp
		 * @param	data
		 */
		public function sendArrayVo(msg:int, stamp:int, data:Vector.<BaseVO>):void {
			var _command:AbstractSocketCommand = new ArraySocketCommand(msg, stamp, data);
			sendCommand(_command);
		}
		/**
		 * 解析远程数据
		 * TODO: 加密解密
		 */
		private function parseCommand():void {
			if (_step == 0) {
				if (_socket.bytesAvailable >= PREHEAD_LENGTH) {
					_len = _socket.readShort();
					_step = 1;
				}
			}
			
			if (_step == 1) {
				if (_socket.bytesAvailable >= this._len) {
					var _byteArray:ByteArray = new ByteArray();
					_socket.readBytes(_byteArray, 0, _len);
					// _byteArray.position = 0;
					var command:AbstractSocketCommand = SocketCommandFactory.instance.unpack(_byteArray);
					_step = 0;
					processCommand(command);
				}
			}
			// 如果缓存里还有数据, 则再做一次
			if (_socket.bytesAvailable > PREHEAD_LENGTH) {
				parseCommand();
			}
		}
		/**
		 * 解析完之后, 需要处理, 发送给相应处理的命令
		 * @param	command
		 */
		private function processCommand(command:AbstractSocketCommand):void {
			var sb:StringBuffer = new StringBuffer();
			sb.append('REMOTE MESSAGE: ');
			sb.append(getQualifiedClassName(command['data']));
			sb.append(', ID:');
			sb.append(command.message());
			_logger.info(sb.toString());

			sendNotification(command.message()+'_REMOTE_MESSAGE', command);
		}
	}
}
